package com.ljb.proxy;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import okhttp3.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

public class VoterDemo {
    private static final String randomChart = "ABCDEF0987654321";
    private static int successCount = 0;
    private static int interval = 1;
    private static int totalCount = 10;
    private static int model = 1;


    public static void main(String[] args) {
        System.err.println("输入投票时间间隔,单位为秒(系统会以该时间为标准随机投票):");
        interval = getIntNum();
        System.err.println("输入投票总次数:");
        totalCount = getIntNum();
        System.err.println("请选择投票模式(1,普通投票;2,代理ip投票):");
        model = getIntNum();
        System.out.println("投票频率为: " + interval + "s ; 投票总次数为: " + totalCount + " ; 投票模式为:" + model);

        if (model == 1) {
            System.out.println("开始投票==============>");
            vote();
            System.out.println("投票结束==============>");
        } else if (model == 2) {
            System.out.println("开始投票==============>");
            proxyVote();
            System.out.println("投票结束==============>");
        } else {
            System.out.println("未知模式,默认选用模式1方式");
            System.out.println("开始投票==============>");
            vote();
            System.out.println("投票结束==============>");
        }
    }

    private static int getIntNum() {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            if (scanner.hasNextInt()) {
                int i = scanner.nextInt();
                if (i > 0) {
                    return i;
                }
            } else {
                scanner.next();
            }
            System.err.println("请输入0以上的整数");
        }
    }


    //代理投票
    private static void proxyVote() {
        List<ProxyIpInfo> proxyIpInfos = fetchProxyIp();
        if (proxyIpInfos.size() <= 0) {
            System.out.println("没有获取到可用代理ip,请重试或选择普通模式!!!.");
            return;
        }

        while (successCount < totalCount) {
            String cookie = ResponseBuilder.getRandomCookie();
            int randomInt = ResponseBuilder.getRandomInt(proxyIpInfos.size());
            ProxyIpInfo proxyIpInfo = proxyIpInfos.get(randomInt);

            for (int j = 0; j < 5 && j < totalCount; j++) {
                try {
                    Thread.sleep(ResponseBuilder.getRandomInt(1500));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Response response = new ResponseBuilder()
                        .setCookie(cookie)
                        .setProxy(proxyIpInfo.getIp(), proxyIpInfo.getPort())
                        .create();
                if (response == null) {
                    break;
                }
                if (response.isSuccessful()) {
                    try {
                        String body = response.body().string();
                        VoteBean voteBean = new Gson().fromJson(body, VoteBean.class);
                        if (voteBean.code == 200) {
                            System.out.println("代理投票成功 timestamp = " + System.currentTimeMillis() / 1000 + " ; 累计成功次数 = " + ++successCount);
                        } else {
                            System.out.println("代理投票失败");
                            break;
                        }
                    } catch (JsonSyntaxException | IOException e) {
//                        e.printStackTrace();
                        break;
                    }
                } else {
                    response.close();
                    System.out.println("代理网络请求失败");
                    break;
                }
            }
            try {
                Thread.sleep(ResponseBuilder.getRandomInt(interval * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //普通投票
    private static void vote() {
        for (int i = 1; i <= totalCount; i++) {
            String cookie = ResponseBuilder.getRandomCookie();
            for (int j = 0; j < 5; j++) {
                try {
                    Thread.sleep(ResponseBuilder.getRandomInt(1500));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Response response = new ResponseBuilder()
                        .setCookie(cookie)
                        .create();
                if (response == null) {
                    break;
                }
                if (response.isSuccessful()) {
                    try {
                        String body = response.body().string();
                        VoteBean voteBean = new Gson().fromJson(body, VoteBean.class);
                        if (voteBean.code == 200) {
                            System.out.println("投票成功 timestamp = " + System.currentTimeMillis() / 1000 + " ; 累计成功次数 = " + ++successCount);
                            i++;
                        } else {
                            System.out.println("投票失败");
                            break;
                        }
                    } catch (IOException | JsonSyntaxException e) {
//                        e.printStackTrace();
                        break;
                    }
                } else {
                    response.close();
                    System.out.println("网络请求失败");
                    break;
                }
            }
            try {
                Thread.sleep(ResponseBuilder.getRandomInt(interval * 1000));
            } catch (InterruptedException e) {
//                e.printStackTrace();
            }
        }
    }

    //获取代理ip
    private static List<ProxyIpInfo> fetchProxyIp() {
        System.out.println("开始捕获免费代理ip,.............waiting..............");
        List<ProxyIpInfo> proxyIpInfos = new ArrayList<>();

        try {
            Document doc = Jsoup.connect("http://www.xicidaili.com/wt/")
                    .timeout(5000)
                    .get();
            Elements trs = doc.select("tr");
            for (Element tr : trs) {
                if (proxyIpInfos.size() >= 10) {
                    break;
                }
                Elements tds = tr.select("td");
                if (tds.size() > 5) {
                    String ip = tds.get(1).text();
                    String port = tds.get(2).text();
                    String type = tds.get(5).text();
                    //提取http类型
                    if (StringUtils.equals("HTTP", type)) {
                        System.out.println("发现代理ip:" + ip + " : " + port);
                        Response response = new ResponseBuilder()
                                .setProxy(ip, Integer.valueOf(port))
                                .create();
                        if (response == null)
                            continue;

                        if (response.isSuccessful()) {
                            String body = response.body().string();
                            try {
                                VoteBean voteBean = new Gson().fromJson(body, VoteBean.class);
                                if (voteBean.code == 200 || voteBean.code == 403) {
                                    ProxyIpInfo proxyIpInfo = new ProxyIpInfo();
                                    proxyIpInfo.setIp(ip);
                                    proxyIpInfo.setPort(Integer.valueOf(port));
                                    proxyIpInfos.add(proxyIpInfo);
                                    System.out.println("测试代理ip : " + ip + " : " + port + "可用");
                                }
                            } catch (JsonSyntaxException | NumberFormatException e) {
//                                e.printStackTrace();
                            }
                        } else {
                            response.close();
                        }
                    }
                }
            }
        } catch (IOException e) {
//            e.printStackTrace();
        }

        System.out.println("免费代理ip捕获完成 +++++++++++++++++++++++++++++");
        return proxyIpInfos;
    }

    /**
     * 网络请求构建器
     */
    private static class ResponseBuilder {
        private MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
        private String requestBody = "go_id=390&action=votes";
        private String proxyIp;
        private int proxyPort;
        private String cookie;

        private ResponseBuilder setProxy(String proxyIp, int proxyPort) {
            this.proxyIp = proxyIp;
            this.proxyPort = proxyPort;
            return this;
        }

        private ResponseBuilder setCookie(String cookie) {
            this.cookie = cookie;
            return this;
        }

        /**
         * 创建Post请求
         *
         * @return
         * @throws IOException
         */
        private Response create() {
            try {
                OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
                        .connectTimeout(10, TimeUnit.SECONDS)
                        .readTimeout(10, TimeUnit.SECONDS)
                        .writeTimeout(10, TimeUnit.SECONDS);
                Request.Builder requestBuilder = new Request.Builder();
                if (!StringUtils.isEmpty(proxyIp) && proxyPort != 0) {
                    clientBuilder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyIp, proxyPort)));
                }
                if (!StringUtils.isEmpty(cookie)) {
                    requestBuilder.addHeader("Cookie", "goldvote_guid=" + cookie);
                }
                Request request = requestBuilder.url("http://special.meirixue.com/2018goldvote/html/goldvote.php")
                        .post(RequestBody.create(mediaType, requestBody))
                        .build();
                return clientBuilder.build().newCall(request).execute();
            } catch (IOException e) {
//                e.printStackTrace();
            }
            return null;
        }

        //获取随机Int数
        private static int getRandomInt(int bound) {
            Random random = new Random();
            return random.nextInt(bound);
        }

        //获取随机Cookie
        private static String getRandomCookie() {
            StringBuilder sb = new StringBuilder();
            sb.append(RandomStringUtils.random(8, randomChart));
            sb.append("-");
            sb.append(RandomStringUtils.random(4, randomChart));
            sb.append("-");
            sb.append(RandomStringUtils.random(4, randomChart));
            sb.append("-");
            sb.append(RandomStringUtils.random(4, randomChart));
            sb.append("-");
            sb.append(RandomStringUtils.random(12, randomChart));
            System.out.println("随机Cookie: " + sb.toString());
            return sb.toString();
        }
    }
}
